import { Injectable } from '@angular/core';
import { cloneDeep, mergeWith } from 'lodash-es';
import { Node, NodeType } from '../entity';
import { FormBindingType, FormComponent, FormDeclaration, FormExpression, FormExternalComponent, FormVariable, FormVariableCategory, FormVariableTypes, FormViewModel, FormViewModelField, FormWebCmd, Subscription } from '../entity/dom-entity';
import { FormMetadaDataDom, FormMetaDataModule } from '../entity/form-metadata';
import { FormTempateOutlineSchema } from '../entity/form-template-outline';
import { FormSchema, FormSchemaEntity, FormSchemaEntityField } from '../entity/schema';
import { DgControl } from './designer-host.service';
import onChange from '@farris/on-change';
const ROOT_VIEW_MODEL_ID = 'root-viewmodel';

/**
 * 操作表单DOM的工具类
 */
@Injectable({
    providedIn: 'root'
})
export class DomService {
    /** 表单元数据结构，实时 */
    private _domJson: FormMetadaDataDom;

    /** 打开表单设计器时的DOM元数据结构，与be数据保持一致 */
    private previousDomJson: FormMetadaDataDom;

    private nodeTypeCollect: Map<string, Node[]> = new Map<string, Node[]>();
    // private nodeIdCollect: Map<string, Node[]> = new Map<string, Node[]>();

    /** 映射JSON结构映射：<控件id, 控件JSON> */
    public domDgMap = new Map<string, any>();

    /** 当前表单所属模板的大纲schema结构 */
    templateOutlineSchema: FormTempateOutlineSchema[];

    /** 控件id与控件展示名称、控件路径的映射 <控件id, {showName:控件展示名称,parentPathName:控件路径} */
    public controlBasicInfoMap = new Map<string, { showName: string, parentPathName: string }>();


    constructor() { }

    /**
     * 设置DOM JSON 数据
     * @param domJson DOM JSON结构
     * @param domChangedCallback DOM结构变化后的回调事件
     */
    setDomJson(domJson: any, domChangedCallback?: (path: string, newValue: any, previousValue: any) => void) {
        if (!domJson || !domJson.module) {
            return;
        }
        this._adaptUpdateVersion(domJson);

        if (domChangedCallback) {
            // 设置代理，监听属性变化
            this._domJson = onChange(domJson, (path, value, previousValue, applyData) => {
                // JSON变更后的回调
                domChangedCallback(path, value, previousValue);
            });
        } else {
            this._domJson = domJson;
        }

    }

    getDomJson() {
        return this._domJson;
    }

    get microApp(): any | null {
        let appinfor: any | null = null;
        try {
            appinfor = window.top['ncdp']['applicationInfo'];
        } catch (error) {
        }
        return appinfor;
    }

    get viewmodels() {
        return this._domJson ? this._domJson.module.viewmodels : null;
    }
    set viewmodels(value) {
        this._domJson.module.viewmodels = value;
    }

    get components(): FormComponent[] {
        return this._domJson.module.components;
    }
    set components(value) {
        this._domJson.module.components = value;
    }

    get options() {
        return this._domJson ? this._domJson.options : null;
    }

    set options(value) {
        this._domJson.options = value;
    }

    get module(): FormMetaDataModule {
        return this._domJson ? this._domJson.module : null;
    }
    set module(value) {
        this._domJson.module = value;
    }

    get webCmds() {
        return this._domJson.module.webcmds;
    }

    get expressions(): FormExpression[] {
        return this._domJson ? this._domJson.module.expressions : null;
    }

    set expressions(value) {
        this._domJson.module.expressions = value;
    }

    /**
     * 设置打开表单设计器时的DOM元数据结构，与be数据保持一致
     */
    setPreviousDomJson(domJson) {
        if (!domJson || !domJson.module) {
            return;
        }
        this.previousDomJson = domJson;
    }
    /**
     * 获取表单设计器时的DOM元数据结构，与be数据保持一致
     */
    getPreviousDomJson() {
        return this.previousDomJson;
    }

    /**
     * 更新控件JSON结构映射
     * @param componentInstanceList 控件实例列表
     */
    updateDomDgMap(componentInstanceList: any[]) {
        this.domDgMap.clear();
        for (const cmp of componentInstanceList) {
            this.domDgMap.set(cmp.id, cmp.component);
        }
    }
    /**
     * 获取schemas节点下的uri (目前仅支持单一数据源)
     */
    getSchemas(): FormSchema {
        const schemas = this._domJson.module.schemas;
        if (!schemas || schemas.length === 0) {
            return;
        }
        return schemas[0];

    }

    setSchemas(schemaObject) {
        if (!schemaObject) {
            return;
        }
        this._domJson.module.schemas = [schemaObject];
    }

    setSchemaEntity(schemEntities: FormSchemaEntity[]) {
        const schema = this.getSchemas();
        schema.entities = schemEntities;
    }

    getQDPInfo() {
        const qdpInfo = this._domJson.module.qdpInfo;
        if (qdpInfo && qdpInfo.qoMetadata && qdpInfo.qoMetadata.length) {
            return qdpInfo;
        } else {
            return null;
        }
    }

    getUpdateVersion() {
        return this._domJson.module.updateVersion;
    }

    get extraImports(): Array<{ name: string, path: string }> {
        return this._domJson ? this._domJson.module.extraImports : null;
    }

    set extraImports(value: Array<{ name: string, path: string }>) {
        this._domJson.module.extraImports = value;
    }

    /**
     * 深层查找控件
     */
    getComponetsByPredicate(predicate: (component) => boolean) {
        const targetComponets = [];
        const predicateFun = predicate;
        const findTarget = (contentComponents) => {
            contentComponents.forEach(function (component) {
                if (predicateFun(component)) {
                    targetComponets.push(component);
                }
                if (component.contents && component.contents.length) {
                    findTarget(component.contents);
                }
            });
        };

        findTarget(this.components);
        return targetComponets;
    }

    /**
     * 根据组件ID获取components下相应的组件节点
     * @param componentId 组件标识
     */
    getComponentById(componentId, deep = false) {
        if (!this.components || this.components.length === 0) {
            return;
        }
        if (deep) {
            const targetComponet = this.getComponetsByPredicate((item) => item.id === componentId);
            return targetComponet ? targetComponet[0] : null;
        } else {
            return this.components.find(cmp => cmp.id === componentId);
        }
    }

    /**
     *  根据VM ID获取相应组件
     * @param viewModelId VMID
     */
    getComponentByVMId(viewModelId: string) {
        return this.components.find(cmp => cmp.viewModel === viewModelId);
    }

    /**
     * 根据viewModelId获取模型节点
     * @param viewModelId 视图模型标识
     */
    getViewModelById(viewModelId): FormViewModel {
        if (!this.viewmodels || this.viewmodels.length === 0 || !viewModelId) {
            return;
        }
        return this.viewmodels.find(vm => vm.id === viewModelId);
    }

    getViewModelFieldById(viewModelId: string, fieldId: string) {
        const vm = this.getViewModelById(viewModelId);
        return vm.fields.find(f => f.id === fieldId);
    }
    getViewModelByFieldId(fieldId: string): FormViewModel {
        let viewModel: FormViewModel;
        for (const vm of this.viewmodels) {
            const field = vm.fields.find(f => f.id === fieldId);
            if (field) {
                viewModel = vm;
                break;
            }
        }
        return viewModel;
    }
    /**
     * 校验指定VM下是否重复绑定字段或变量
     * @param viewModelId 视图模型标识
     * @param newFieldId 字段标识
     */
    checkViewModelDulplicated(viewModelId, newFieldId) {
        if (!viewModelId || !newFieldId) {
            return;
        }
        const viewModel = this.getViewModelById(viewModelId);

        // 判断重复绑定
        const exsitVM = viewModel.fields.find(f => f.id === newFieldId);
        if (exsitVM) {
            return true;
        }
        return false;
    }
    /**
     * 修改ViewModel Field
     * @param viewModelId VM ID
     * @param fieldId 修改前binding.field取值
     * @param changeObject 变更集
     */
    modifyViewModelFieldById(viewModelId, fieldId, changeObject, isMerge = true) {
        if (!viewModelId || !changeObject) {
            return;
        }
        const viewModel = this.getViewModelById(viewModelId);
        let field;
        if (fieldId) {
            field = viewModel.fields.find(f => f.id === fieldId);
        }
        function customizer(objValue, srcValue) {
            if (!isMerge) {
                return srcValue;
            } else if (Array.isArray(objValue)) {
                return srcValue;
            }
        }
        if (field) {
            // 数组类型不再合并，全量替换：用户枚举数据的更改
            mergeWith(field, changeObject, customizer);
        } else {
            changeObject.groupId = null;
            changeObject.groupName = null;
            this.addViewModelField(viewModelId, changeObject);
        }
    }

    /**
     * 控件新增绑定添加ViewModel Field
     */
    addViewModelField(viewModelId, filedObject: FormViewModelField) {
        if (!viewModelId || !filedObject) {
            return;
        }
        const viewModel = this.getViewModelById(viewModelId);

        if (!viewModel.fields.find(field => field.id === filedObject.id)) {
            viewModel.fields.push(filedObject);
        }

    }

    /**
     * 根据VMID修改ViewModel节点
     * @param vmId  视图模型标识
     * @param vmFields 字段集合
     */
    setViewModelFieldsById(vmId, vmFields) {
        if (!this.viewmodels || this.viewmodels.length === 0 || !vmId) {
            return;
        }
        const oldVM = this.viewmodels.find(vm => vm.id === vmId);
        oldVM.fields = vmFields;
    }

    /**
     * 修改VM字段的分组名称
     * @param viewModelId 视图模型标识
     * @param groupId 分组标识
     * @param groupName 分组名称
     */
    modifyGroupNameById(viewModelId, groupId, groupName) {
        const vm = this.getViewModelById(viewModelId);
        vm.fields.forEach(field => {
            if (field.groupId !== groupId) { return; }
            field.groupName = groupName;
        });
    }

    /**
     * 根据ID删除ViewModel中的field节点
     * @param viewModelId 视图模型标识
     * @param fieldId 字段标识
     */
    deleteViewModelFieldById(viewModelId: string, fieldId: string) {
        if (!viewModelId || !fieldId) {
            return;
        }
        const viewModel = this.getViewModelById(viewModelId);
        if (!viewModel) {
            return;
        }
        viewModel.fields = viewModel.fields.filter(f => f.id !== fieldId);
    }

    /**
     * 清除视图模型中针对字段的修改
     * @param viewModelId 视图模型标识
     * @param fieldId 字段标识
     */
    clearViewModelFieldSchema(viewModelId, fieldId) {
        if (!viewModelId) {
            return;
        }
        const viewModel = this.getViewModelById(viewModelId);
        let field;
        if (fieldId) {
            field = viewModel.fields.find(f => f.id === fieldId);
        }
        if (field) {
            field.fieldSchema = {};
        }
    }
    /**
     * 根据ID删除整个ViewModel
     * @param viewModelId 视图模型标识
     */
    deleteViewModelById(viewModelId) {
        const index = this.viewmodels.findIndex(vm => vm.id === viewModelId);
        this.viewmodels.splice(index, 1);
    }

    /**
     * 删除dom中components下的组件节点
     * @param cmpId 组件ID
     */
    deleteComponent(cmpId: string) {
        if (!this._domJson || !this._domJson.module || !cmpId || !this._domJson.module.components) {
            return [];
        }
        this._domJson.module.components = this._domJson.module.components.filter(c => c.id !== cmpId);
    }

    /*
     * 获取表单引用的命令构件信息
     */
    getWebCmds(): FormWebCmd[] {
        return this._domJson.module.webcmds;
    }

    getServiceRefs(): any[] {
        return this._domJson.module.serviceRefs || [];
    }

    /**
     * 获取表单ViewModel中的命令，构建treetable数据，用于事件的选择窗口
     * 树表中额外增加commandPath属性(命令所在viewModelId.commandCode)，用于窗口展开时数据行的回显。
     */
    getCommandsTreeTable(viewModelId: string, showEmptyViewModelNode = false) {
        if (!this.viewmodels || this.viewmodels.length === 0) {
            return;
        }
        const commandTree = [];
        // 获取根ViewModel和其他所有ViewModel的命令
        if (!viewModelId || viewModelId === ROOT_VIEW_MODEL_ID) {

            for (let index = 0; index < this.viewmodels.length; index++) {
                const viewModel = this.viewmodels[index];
                if (viewModel.fakeDel) {
                    continue;
                }
                const children = [];

                viewModel.commands.forEach(command => {
                    children.push({ data: { ...command, commandPath: viewModel.id + '.' + command.code }, children: [], selectable: true });
                });


                if (showEmptyViewModelNode || children.length) {
                    commandTree.push({
                        data: { id: viewModel.id, code: viewModel.code, name: viewModel.name + '视图模型', commandPath: viewModel.id },
                        children,
                        selectable: false, expanded: true
                    });
                }

            }
            let rootVm;
            if (commandTree.length > 1) {
                // 根节点
                rootVm = commandTree[0];
                const childVmList = commandTree.slice(1, commandTree.length);
                rootVm.children.push(...childVmList);
                return [rootVm];
            }
            return commandTree;
        }

        // 获取指定viewModel的命令
        const selectedViewModel = this.viewmodels.find(vm => vm.id === viewModelId);
        selectedViewModel.commands.forEach(command => {
            commandTree.push({
                data: { ...command, commandPath: selectedViewModel.id + '.' + command.code },
                children: [], selectable: true
            });
        });
        if (commandTree.length) {
            return [{
                data: {
                    id: selectedViewModel.id, code: selectedViewModel.code, name: selectedViewModel.code + '视图模型',
                    commandPath: selectedViewModel.id
                },
                children: commandTree,
                selectable: false,
                expanded: true
            }];
        }
        return [];


    }

    /**
     * 获取所有的命令，平铺成数组
     */
    getAllPlainCommands(): any[] {
        if (!this.viewmodels || this.viewmodels.length === 0) {
            return;
        }
        const commands = [];
        // 获取根ViewModel和其他所有ViewModel的命令
        this.viewmodels.forEach(viewModel => {
            viewModel.commands.forEach(command => {
                commands.push({ ...command, commandPath: viewModel.id + '.' + command.code });
            });
        });
        return commands;
    }

    /**
     * 获取ViewModel中组件上下文变量，构建treetable数据，用于变量绑定的选择窗口
     */
    getLocaleVariablesByViewModelId(viewModelId: string) {
        if (!this.viewmodels || this.viewmodels.length === 0) {
            return [];
        }
        const viewModel = this.getViewModelById(viewModelId);
        if (!viewModel || !viewModel.states || viewModel.states.length === 0) {
            return [];
        }

        const children = [];
        viewModel.states.forEach(variable => {
            if (!variable.category || variable.category === FormVariableCategory.locale) {
                // 增加中文类型名称，用于界面展示
                let displayTypeName = variable.type;
                const vt = FormVariableTypes.find(v => v.value === variable.type);
                if (vt) {
                    displayTypeName = vt.text;
                }

                children.push({ data: { ...variable, displayTypeName }, children: [], selectable: true, viewModelId });
            }
        });

        if (!children.length) {
            return [];
        }
        const rootVm = {
            data: { id: viewModel.id, name: viewModel.name + '组件' },
            children,
            selectable: false,
            expanded: true,
            nodeType: 'vmNode'
        };

        return [rootVm];
    }
    /**
     * 获取ViewModel中远程（VO）上下文变量，构建treetable数据，用于变量绑定的选择窗口
     */
    getRemoteVariables() {
        if (!this.viewmodels || this.viewmodels.length === 0) {
            return [];
        }
        const viewModel = this.getViewModelById(this.getRootViewModelId());
        if (!viewModel || !viewModel.states || viewModel.states.length === 0) {
            return [];
        }

        const children = [];
        viewModel.states.forEach(variable => {
            if (variable.category === FormVariableCategory.remote) {
                // 增加中文类型名称，用于界面展示
                let displayTypeName = variable.type;
                const vt = FormVariableTypes.find(v => v.value === variable.type);
                if (vt) {
                    displayTypeName = vt.text;
                }

                children.push({ data: { ...variable, displayTypeName }, children: [], selectable: true });
            }
        });
        return children;
    }

    /**
     * 更新远程变量
     * @param varList 变量列表
     */
    updateRemoteVariables(varList: FormSchemaEntityField[]) {
        if (!this.viewmodels || this.viewmodels.length === 0) {
            return;
        }
        const viewModel = this.getViewModelById(this.getRootViewModelId());
        const currentStates = viewModel.states.filter(s => s.category === 'remote');
        const vmVarList = this.changeSchemaVariable2VMVariable(varList);

        // 为了不引起DOM JSON的变更，增加判断
        if (currentStates && vmVarList && JSON.stringify(currentStates) !== JSON.stringify(vmVarList)) {
            viewModel.states = viewModel.states.filter(s => !s.category || s.category === 'locale');
            viewModel.states.push(...vmVarList);
        }
    }

    /**
     * schema中的变量转换为VM上的变量
     * @param schemaVarList 变量列表
     */
    private changeSchemaVariable2VMVariable(schemaVarList: FormSchemaEntityField[]) {
        if (!schemaVarList || schemaVarList.length === 0) {
            return [];
        }
        const vmVarList: FormVariable[] = [];
        schemaVarList.forEach(v => {
            const rv: FormVariable = {
                id: v.id,
                code: v.label,
                name: v.name,
                defaultValue: v.defaultValue,
                type: v.type.name,
                category: 'remote'
            };
            if (v.$type !== 'SimpleField' && v.type.fields) {
                rv.type = 'Object';
                rv.fields = this.changeSchemaVariable2VMVariable(v.type.fields);
            }

            vmVarList.push(rv);
        });
        return vmVarList;
    }
    /**
     * 保存变量(全量)
     * @param states 变量列表
     * @param viewModelId 变量所属viewModel ID
     */
    saveVariables(states: FormVariable[], viewModelId: string) {
        if (!this.viewmodels || this.viewmodels.length === 0) {
            return;
        }
        const viewModel = this.getViewModelById(viewModelId);
        viewModel.states.length = 0;
        viewModel.states.push(...states);
    }

    /**
     * 获取指定变量
     */
    getVariableByIdAndVMID(varId: string, viewModelId: string) {
        if (!this.viewmodels || this.viewmodels.length === 0) {
            return;
        }
        const viewModel = this.getViewModelById(viewModelId);
        const variable = viewModel.states.find(v => v.id === varId);
        return variable;
    }

    /**
     * 获取指定变量
     */
    getVariableById(varId: string) {
        if (!this.viewmodels || this.viewmodels.length === 0) {
            return;
        }
        for (const viewModel of this.viewmodels) {
            const variable = viewModel.states.find(v => v.id === varId);
            if (variable) {
                return variable;
            }
        }
    }
    /**
     * 获取所有VM下的变量，组装成树结构
     * 树表中额外增加statePath属性(命令所在viewModelId.variableCode)，用于窗口展开时数据行的回显。
     */
    getAllVariables() {
        if (!this.viewmodels || this.viewmodels.length === 0) {
            return [];
        }
        const vmTree = [];
        this.viewmodels.forEach(viewModel => {
            if (!viewModel || !viewModel.states || viewModel.states.length === 0) {
                return [];
            }

            const children = [];
            viewModel.states.forEach(variable => {
                children.push({ data: { ...variable, statePath: viewModel.id + '.' + variable.code }, children: [], selectable: true });
            });

            const rootVm = {
                data: { id: viewModel.id, code: viewModel.code, name: viewModel.name + '视图模型', statePath: viewModel.id },
                children,
                selectable: false, expanded: true
            };
            vmTree.push(rootVm);

        });
        return vmTree;
    }

    /**
     * 获取所有VM下的变量并平铺成数组
     * 额外增加statePath属性(命令所在viewModelId.variableCode)，用于唯一标识
     */
    getAllPlainVariables(): any[] {
        if (!this.viewmodels || this.viewmodels.length === 0) {
            return [];
        }
        const varArray = [];
        this.viewmodels.forEach(viewModel => {
            if (!viewModel || !viewModel.states || viewModel.states.length === 0) {
                return [];
            }
            viewModel.states.forEach(variable => {
                varArray.push({ ...variable, statePath: viewModel.id + '.' + variable.code });
            });
        });
        return varArray;
    }

    /**
     * 1月3号以前的盘中缺失updateVersion字段，默认添加181225（上一次执行表单升级工具后的统一版本号）
     */
    _adaptUpdateVersion(domJson: any) {
        if (!domJson.module.updateVersion) {
            domJson.module.updateVersion = '181225';
        }
    }


    /**
     * 获取组件声明
     */
    getComponentDeclarations(): FormDeclaration {
        if (!this._domJson || !this._domJson.module) {
            return {};
        }
        return this._domJson.module.declarations;
    }
    /**
     * 修改组件事件声明
     * @param data 组件声明数据
     */
    setComponentDeclarations(data) {
        this._domJson.module.declarations = data;
    }

    /**
     * 获取事件订阅
     */
    getComponentSubscriptions(sourceComponent = ''): Subscription[] {
        if (!this._domJson || !this._domJson.module || !this._domJson.module.subscriptions ||
            this._domJson.module.subscriptions.length === 0) {
            return [];
        }
        if (!sourceComponent) {
            return this._domJson.module.subscriptions;
        }
        const subList = this._domJson.module.subscriptions.filter(sub => sub.sourceComponent === sourceComponent);
        return subList;
    }

    /**
     * 修改事件订阅
     * @param data 事件订阅数据
     */
    setComponentSubscriptions(data = []) {
        if (!this._domJson || !this._domJson.module) {
            return;
        }
        this._domJson.module.subscriptions = data;
    }

    deleteComponentSubscription(cmpId: string) {
        if (!this._domJson || !this._domJson.module || !this._domJson.module.subscriptions) {
            return;
        }

        const subscriptions = this._domJson.module.subscriptions;
        this._domJson.module.subscriptions = subscriptions.filter(
            (item) => item.sourceComponent !== cmpId
        );
    }

    /**
     * 设置外部组件信息
     * @param cmpInfo 组件信息
     * @param cmpId 外部组件id
     */
    setExternalComponent(cmpInfo: any, cmpId: string) {
        if (!this._domJson || !this._domJson.module) {
            return;
        }
        if (!this._domJson.module.externalComponents) {
            this._domJson.module.externalComponents = [];
        }
        if (!cmpId) { // 新增
            // if (cmpInfo.type === DgControl.ModalContainer.type) { // ModalContainer与内部实体是一对一映射
            //     const externalComponentArray = this.getExternalComponentByContainerId(cmpInfo.containerId);
            //     if (externalComponentArray !== undefined && externalComponentArray !== null && externalComponentArray.length > 0) {
            //         externalComponentArray.forEach(externalComponent => {
            //             this.deleteExternalComponent(externalComponent.id);
            //         });
            //     }
            // }
            this._domJson.module.externalComponents.push(cmpInfo);
        } else {
            // 修改
            this._domJson.module.externalComponents = this._domJson.module.externalComponents.filter(e => e.id !== cmpId);
            this._domJson.module.externalComponents.push(cmpInfo);

        }

        // 更新组合表单标识
        if (this._domJson.module.externalComponents.length === 0) {
            this._domJson.module.isComposedFrm = false;
        } else {
            this._domJson.module.isComposedFrm = true;
        }
    }
    /**
     * 根据容器ID获取外部组件节点
     * @param containerId 容器ID
     * 由ExternalContainer、ModalContainer引入的外部组件，containerId是容器id
     * 筛选方案中智能输入框弹出表单的场景：containerId是绑定字段id
     */
    getExternalComponentByContainerId(containerId: string): FormExternalComponent {
        if (!this._domJson || !this._domJson.module || !this._domJson.module.externalComponents || !containerId) {
            return;
        }
        return this._domJson.module.externalComponents.find(e => e.containerId === containerId);
    }

    /**
     * 根据ID获取外部组件
     * @param cmpId 组件ID
     */
    getExternalComponent(cmpId = ''): FormExternalComponent[] {
        if (!this._domJson || !this._domJson.module || !this._domJson.module.externalComponents) {
            return [];
        }

        // 筛选当前生效的外部组件：一些场景下externalComponents节点下会出现冗余的组件 TODO 待优化
        // const compStr = JSON.stringify(this._domJson.module.components);
        // if (this._domJson.module.externalComponents && this._domJson.module.externalComponents.length) {
        //     this._domJson.module.externalComponents = this._domJson.module.externalComponents.filter(element => {
        //         if (compStr.indexOf(element.id) < 0) {
        //             return false;
        //         }
        //         return true;
        //     });
        // }

        if (!cmpId) {
            return this._domJson.module.externalComponents;
        }
        return this._domJson.module.externalComponents.filter(e => e.id === cmpId);
    }

    /**
     * 删除外部组件
     * @param cmpId  组件id
     */
    deleteExternalComponent(cmpId: string) {
        if (!this._domJson || !this._domJson.module || !cmpId || !this._domJson.module.externalComponents) {
            return [];
        }
        this._domJson.module.externalComponents = this._domJson.module.externalComponents.filter(c => c.id !== cmpId);

        // 更新组合表单标识
        if (this._domJson.module.externalComponents.length === 0) {
            this._domJson.module.isComposedFrm = false;
        } else {
            this._domJson.module.isComposedFrm = true;
        }
    }



    /**
     * 获取指定VM关联的组件中绑定指定字段的控件（目前只有一个控件）
     * @param viewModelId VM标识
     * @param fieldId   字段标识
     */
    getControlsInCmpWidthBinding(viewModelId: string, fieldId: string) {
        const cmp = this.components.find(c => c.viewModel === viewModelId);

        return this.getControlsByBinding(cmp.contents, fieldId);
    }

    /**
     * 获取指定VM关联的组件中绑定指定字段的控件
     * @param contents DOM节点
     * @param fieldId 字段标识
     */
    private getControlsByBinding(contents: any[], fieldId: string) {
        let controls = [];
        for (const element of contents) {
            if ((DgControl.DataGrid && element.type === DgControl.DataGrid.type ) || (DgControl.TreeGrid && element.type === DgControl.TreeGrid.type)) { // 列表
                const childControls = this.getControlsByBinding(element.fields, fieldId);
                controls = controls.concat(childControls);
            } else if (DgControl.Table && element.type === DgControl.Table.type) { // Table
                const tdControls = this.getControlEditorsInTable(element.rows, fieldId);
                controls = controls.concat(tdControls);
            } else if (element.contents) { // 容器组件
                const childControls = this.getControlsByBinding(element.contents, fieldId);
                controls = controls.concat(childControls);
            } else if (element.binding && element.binding.type === FormBindingType.Form && element.binding.field === fieldId) {
                controls.push(element);
            }
        }

        return controls;
    }

    private getControlEditorsInTable(tableRows: any[], fieldId: string) {
        const controls = [];
        if (tableRows && tableRows.length) {
            tableRows.forEach(row => {
                row.columns.forEach(column => {
                    if (column.tdType === 'editor' && column.editor && column.editor.binding) {
                        if (column.editor.binding.type && column.editor.binding.type === FormBindingType.Form && column.editor.binding.field === fieldId) {
                            controls.push(column.editor);
                        }
                    }
                });
            });
        }

        return controls;
    }

    /**
     *  获取节点下所有 components ID 列表
     * @param eleContents []
     * @returns string[]
     */
    getALLComponentsIDList(eleContents: { type: string, component: any, contents: [] }[]): string[] {
        let deIDList = [];
        eleContents.forEach(element => {
            if (element.type === 'ComponentRef') {
                const targetComponents = this.components.find((item) => {
                    return item.id === element.component;
                });
                deIDList.push(targetComponents.id);
                // 这段没有必要，因为没有嵌套的component
                if (targetComponents && targetComponents.contents) {
                    if (targetComponents.contents && targetComponents.contents.length) {
                        deIDList = deIDList.concat(this.getALLComponentsIDList(targetComponents.contents));
                    }
                }
            }
            if (element.contents && element.contents.length) {
                deIDList = deIDList.concat(this.getALLComponentsIDList(element.contents));
            }
        });
        return deIDList;
    }

    /**
     * 添加component 方法
     */
    addComponent(component: FormComponent): string {
        // 不再复用之前删除的Component
        // let oldComponentIndex = 0;
        // const oldComponent = this.components.find((item, index) => {
        //     oldComponentIndex = index;
        //     return item.viewModel === component.viewModel && item.fakeDel;
        // });
        // if (oldComponent) {
        //     component.id = oldComponent.id;
        //     this.components[oldComponentIndex] = component;
        // } else {
        this.components.push(component);
        // }
        return component.id;
    }

    /**
     * 添加 viewModel 方法
     * @param viewModel：FormViewModel
     * @returns string viewModel id
     */
    public addViewModel(viewModel: FormViewModel): string {
        // 不再复用之前删除的viewModel
        // let oldViewModelIndex = 0;
        // const oldViewModel = this.viewmodels.find((item, index) => {
        //     oldViewModelIndex = index;
        //     return item.bindTo === viewModel.bindTo && item.fakeDel;
        // });
        // if (oldViewModel) {
        //     viewModel.id = oldViewModel.id;
        //     this.viewmodels[oldViewModelIndex] = viewModel;
        // } else {
        this.viewmodels.push(viewModel);
        // }
        return viewModel.id;
    }

    /**
     * 场景：在表单上删除tabPage/datagrid后，不能真正删除component和viewModel节点，不然会造成编译错误，故将component和viewmodel标记为fakeDel
     */
    remarkComponentFakeDel(removedComponentIdList: string[]): void {
        removedComponentIdList.forEach(element => {
            const targetComponent = this.getComponentById(element);
            const targetViewModel = this.getViewModelById(targetComponent.viewModel);
            targetViewModel.fakeDel = true;
            targetComponent.fakeDel = true;
        });
    }


    /**
     * 根据指定的条件遍历查找节点
     * @param rootNode 容器节点
     * @param predict 条件
     */
    selectNode(rootNode: any, predict: (item: any) => boolean) {
        if (!rootNode) {
            return null;
        }
        if (predict(rootNode)) {
            return rootNode;
        }
        if (rootNode.contents) {
            for (const item of rootNode.contents) {
                const found = this.selectNode(item, predict);
                if (found) {
                    return found;
                }
            }
        }
        return null;
    }

    /**
     * 根据指定的条件遍历查找节点，返回节点及其父节点
     * @param rootNode 容器节点
     * @param predict 预设的判断逻辑
     * @param parentNode 父节点
     */
    selectNodeAndParentNode(rootNode: any, predict: (item: any) => boolean, parentNode: any): { node: any, parentNode: any } {
        if (!rootNode) {
            return null;
        }
        if (predict(rootNode)) {
            return {
                node: rootNode,
                parentNode
            };
        }
        if (rootNode.contents) {
            for (const item of rootNode.contents) {
                const found = this.selectNodeAndParentNode(item, predict, rootNode);
                if (found) {
                    return found;
                }
            }
        }
        return null;
    }

    /**
     * 根据id路径定位节点
     * @param rootNode 根节点
     * @param idPath id路径
     */
    getNodeByIdPath(rootNode: any, idPath: string) {
        if (!rootNode || !idPath) {
            return null;
        }
        const idPathArray = idPath.split('.');
        if (idPathArray.length === 0) {
            return;
        }
        const currentId = idPathArray.shift();
        if (rootNode.contents) {
            for (const item of rootNode.contents) {
                if (currentId === '*') {
                    // 任意路径
                    const nextItem = this.selectNodeByWildcardID(item, idPathArray[0]);
                    if (nextItem) {
                        idPathArray.shift();
                        if (idPathArray.length === 0) {
                            return nextItem;
                        }
                        const found = this.getNodeByIdPath(nextItem, idPathArray.join('.'));
                        if (found) {
                            return found;
                        }
                    }

                } else if ((currentId.includes('*') && item.id.startsWith(currentId.slice(0, currentId.length - 1)))
                    || item.id === currentId) {

                    if (idPathArray.length === 0) {
                        return item;
                    } else {
                        const found = this.getNodeByIdPath(item, idPathArray.join('.'));
                        if (found) {
                            return found;
                        }
                    }
                }
            }
        }
        return null;
    }

    /**
     * 根据id遍历查找节点(id支持带有*号的通配符)
     * @param rootNode 容器节点
     * @param predict 条件
     */
    private selectNodeByWildcardID(rootNode: any, id: string) {
        if (!rootNode || !id) {
            return null;
        }
        let flag = false;
        if (id.includes('*')) {
            const newId = id.replace('*', '');
            if (rootNode.id.includes(newId)) {
                flag = true;
            }
        } else if (rootNode.id === id) {
            flag = true;
        }

        if (flag) {
            return rootNode;
        }
        if (rootNode.contents) {
            for (const item of rootNode.contents) {
                const found = this.selectNodeByWildcardID(item, id);
                if (found) {
                    return found;
                }
            }
        }
        return null;
    }

    /**
     * 获取指定控件id的父节点
     * @param rootNode 根组件节点
     * @param id 指定控件的ID
     */
    getControlParentById(rootNode: any, controlId: string): any {
        if (!rootNode) {
            return null;
        }

        if (rootNode.contents) {
            for (const item of rootNode.contents) {
                if (item.id === controlId) {
                    return rootNode;
                } else {
                    const found = this.getControlParentById(item, controlId);
                    if (found) {
                        return found;
                    }
                }

            }
        }
        return null;
    }
    /**
     * 根据ID路径查找所有节点，找到所有符合idPath的最后一位的节点
     * @param rootNode 容器节点
     * @param idPath id路径
     */
    getNodesByIdPath(rootNode: any, idPath: string) {
        if (!rootNode || !idPath) {
            return null;
        }
        const idPathArray = idPath.split('.');
        if (idPathArray.length === 0) {
            return;
        }
        const currentId = idPathArray.shift();
        if (rootNode.contents) {
            for (const item of rootNode.contents) {
                if (currentId === '*') {

                    if (idPathArray.length === 1 && item.contents && item.contents.length) {
                        return item.contents.filter(c => c.id.includes(idPathArray[0].replace('*', '')));
                    }


                    // 任意路径
                    const nextItem = this.selectNodeByWildcardID(item, idPathArray[0]);
                    if (nextItem) {
                        idPathArray.shift();
                        if (idPathArray.length === 0) {
                            return [nextItem];
                        }
                        const found = this.getNodeByIdPath(nextItem, idPathArray.join('.'));
                        if (found) {
                            return [found];
                        }
                    }

                } else if ((currentId.includes('*') && item.id.startsWith(currentId.slice(0, currentId.length - 1)))
                    || item.id === currentId) {

                    if (idPathArray.length === 0) {
                        return [item];
                    } else {
                        const found = this.getNodesByIdPath(item, idPathArray.join('.'));
                        if (found) {
                            return found;
                        }
                    }
                }
            }
        }
        return null;
    }


    /**
     * 根据控件所在组件的统一布局配置获取控件样式
     * @param componentId 组件Id
     */
    getControlClassByFormUnifiedLayout(controlClass: string, componentId: string) {
        const componentNode = this.getComponentById(componentId);

        if (!componentNode || !componentNode.componentType.startsWith('form')) {
            return controlClass;
        }
        const formNode = this.selectNode(componentNode, item => item.type === DgControl.Form.type);
        if (!formNode || !formNode.unifiedLayout) {
            return controlClass;
        }

        const controlClassArray = controlClass.split(' ');

        let colClass = controlClassArray.find(item => /^col-([1-9]|10|11|12)$/.test(item));
        let colMDClass = controlClassArray.find(item => /^col-md-([1-9]|10|11|12)$/.test(item));
        let colXLClass = controlClassArray.find(item => /^col-xl-([1-9]|10|11|12)$/.test(item));
        let colELClass = controlClassArray.find(item => /^col-el-([1-9]|10|11|12)$/.test(item));


        colClass = formNode.unifiedLayout.uniqueColClassInSM ? 'col-' + formNode.unifiedLayout.uniqueColClassInSM : colClass;
        colMDClass = formNode.unifiedLayout.uniqueColClassInMD ? 'col-md-' + formNode.unifiedLayout.uniqueColClassInMD : colMDClass;
        colXLClass = formNode.unifiedLayout.uniqueColClassInLG ? 'col-xl-' + formNode.unifiedLayout.uniqueColClassInLG : colXLClass;
        colELClass = formNode.unifiedLayout.uniqueColClassInEL ? 'col-el-' + formNode.unifiedLayout.uniqueColClassInEL : colELClass;

        return colClass + ' ' + colMDClass + ' ' + colXLClass + ' ' + colELClass;

    }

    /**
     * 获取所有隐藏帮助
     */
    getHidenLookups() {
        const result = [];
        this.nodeTypeCollect.clear();
        const nodes = cloneDeep(this._domJson.module.components);
        this.collectMetadata(nodes, null);
        if (this.nodeTypeCollect && this.nodeTypeCollect.size > 0) {
            // 找到所有的隐藏区域
            const hiddenContainers = this.nodeTypeCollect.get(NodeType.HiddenContainer);
            if (hiddenContainers && hiddenContainers.length > 0) {
                const containerIds = hiddenContainers.map(item => item.id);
                const lookupEdits = this.nodeTypeCollect.get(NodeType.LookupEdit);
                if (lookupEdits && lookupEdits.length > 0) {
                    const hiddenHelps = lookupEdits.filter(node => containerIds.includes(node.__parentId__));
                    result.push(...hiddenHelps);
                }
            }
        }
        return result;
    }
    /**
     * 获取所有子表弹出编辑组件
     * @returns 
     */
    getPageModalComponents() {
        const result = [];
        this.nodeTypeCollect.clear();
        const nodes = cloneDeep(this._domJson.module.components);
        this.collectMetadata(nodes, null);
        if (this.nodeTypeCollect && this.nodeTypeCollect.size > 0) {
            // 找到所有的隐藏区域
            const components = this.nodeTypeCollect.get(NodeType.Component);
            if (components && components.length > 0) {
                const modals = components.filter(item => item.componentType === 'modalFrame');
                if (modals && modals.length > 0) {
                    result.push(...modals);
                }
            }
        }
        return result;
    }
    /**
   * 遍历节点下所有节点
   * @param root 根节点或contents
   * @param parentId 父节点id
   * @returns 
   */
    private collectMetadata(root: Node | Node[], parentId?: string) {
        if (Array.isArray(root)) {
            root.forEach((node: Node) => {
                this.collectMetadata(node, parentId);
            });
        } else {
            const { id = null, type = null, contents = null } = root;
            if (!id || !type) {
                return;
            }
            root.__parentId__ = parentId;
            const typeValue = this.nodeTypeCollect.get(type) || [];
            typeValue.push(root);
            this.nodeTypeCollect.set(type, typeValue);
            // const idValue = this.nodeIdCollect.get(id) || [];
            // idValue.push(root);
            // this.nodeIdCollect.set(id, idValue);
            if (contents && contents.length > 0) {
                this.collectMetadata(root.contents, id);
            }
        }
    }

    public getRootViewModelId(): string {
        if (this.viewmodels == null || this.viewmodels.length === 0) {
            return ROOT_VIEW_MODEL_ID;
        }

        if(this.viewmodels.find(viewmodel=>viewmodel.id === ROOT_VIEW_MODEL_ID)){
            return ROOT_VIEW_MODEL_ID;

        }

        return this.viewmodels[0].id;
    }
}
